package com.funong.matrix.core.utils;

import cn.hutool.core.util.StrUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter;
import java.util.Date;

/**
 * @author wanjialin
 * @version 1.0
 * @date 2023/5/19
 */
@Slf4j
@Component
public class JwtUtils {

    //常量
    public static final long EXPIRE = 1000 * 60 * 60 * 24L;                     // token过期时间
    public static final long REFRESH_EXPIRE = 1000 * 60 * 60 * 24 * 30L;

    public static final String SECRET_KEY = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO"; //秘钥
    public static final String REFRESH_SECRET_KEY = "ukc8BDbRigUDaY6pZFfWus2jAADASzxzc"; //秘钥

    private Integer huanghe = 86400000;
    private Integer kunlun = 259200000;

    //生成token字符串的方法
    public String getJwtTokenByEmail(String id, String account, String name, boolean isMagellan, Integer systemId, Integer customerId, Integer customerAdmin) {
        Integer expire = isMagellan ? huanghe : kunlun;
        return Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                .setSubject("ctrm")
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + expire))
                .claim("id", id)
                .claim("account", account)
                .claim("name", name)
                .claim("systemId", systemId)
                .claim("customerId", customerId)
                .claim("customerAdmin", customerAdmin)
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }

    public String getJwtTokenByPhone(String id, String phone, boolean isMagellan) {
        Integer expire = isMagellan ? huanghe : kunlun;
        return Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                .setSubject("navigator")
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + expire))
                .claim("id", id)
                .claim("phone", phone)
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }


    public static String getRefreshTokenByEmail(String id, String email) {
        return Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                .setSubject("navigator")
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + REFRESH_EXPIRE))
                .claim("id", id)
                .claim("email", email)
                .signWith(SignatureAlgorithm.HS256, REFRESH_SECRET_KEY)
                .compact();
    }

    public static String getRefreshTokenByPhone(String id, String phone) {
        return Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                .setSubject("navigator")
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + REFRESH_EXPIRE))
                .claim("id", id)
                .claim("phone", phone)
                .signWith(SignatureAlgorithm.HS256, REFRESH_SECRET_KEY)
                .compact();
    }


    /**
     * 判断token是否存在与有效
     *
     * @param jwtToken
     * @return
     */
    public static boolean checkToken(String jwtToken) {
        if (StringUtils.isEmpty(jwtToken)) return false;
        try {
            Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(jwtToken);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 判断token是否存在与有效
     *
     * @param request
     * @return
     */
    public static boolean checkToken(HttpServletRequest request) {
        try {
            String jwtToken = request.getHeader("token");
            if (StringUtils.isEmpty(jwtToken)) return false;
            Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(jwtToken);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 根据token字符串获取会员id
     *
     * @param request
     * @return
     */
    public static String getMemberIdByJwtToken(HttpServletRequest request) {
        Claims claims = parse(request);
        return claims == null ? "" : (String) claims.get("id");
    }

    /**
     * 根据token字符串获取会员id
     *
     * @param request
     * @return
     */
    public static Date getExpirationByJwtToken(HttpServletRequest request) {
        Claims claims = parse(request);
        return claims == null ? new Date() : claims.getExpiration();
    }

    /**
     * 根据token字符串获取会员username
     *
     * @param request
     * @return
     */
    public static String getEmailByJwtToken(HttpServletRequest request) {
        Claims claims = parse(request);
        return claims == null ? "" : (String) claims.get("email");
    }


    /**
     * 根据token字符串获取会员username
     *
     * @param request
     * @return
     */
    public static String getPhoneByJwtToken(HttpServletRequest request) {
        Claims claims = parse(request);
        return claims == null ? "" : (String) claims.get("phone");
    }

    /**
     * 解析JWT
     *
     * @return 解析成功返回Claims对象，解析失败返回null
     */
    public static Claims parse(HttpServletRequest request) {

        String token = request.getHeader("token");

        // 如果是空字符串直接返回null
        if (!StringUtils.hasLength(token)) {
            return null;
        }

        Claims claims = null;
        // 解析失败了会抛出异常，所以我们要捕捉一下。token过期、token非法都会导致解析失败
        try {
            claims = Jwts.parser()
                    .setSigningKey(SECRET_KEY)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (JwtException e) {
            log.error("token解析失败:{}", e.toString());
        }
        return claims;
    }


    /**
     * 解析JWT
     *
     * @return 解析成功返回Claims对象，解析失败返回null
     */
    public static Claims parseRefreshToken(String refreshToken) {
        // 如果是空字符串直接返回null
        if (!StringUtils.hasLength(refreshToken)) {
            return null;
        }
        Claims claims = null;
        // 解析失败了会抛出异常，所以我们要捕捉一下。token过期、token非法都会导致解析失败
        try {
            claims = Jwts.parser()
                    .setSigningKey(REFRESH_SECRET_KEY)
                    .parseClaimsJws(refreshToken)
                    .getBody();
        } catch (JwtException e) {
            log.error("refreshToken解析失败:{}", e.toString());
        }
        return claims;
    }

    //验证和读取JWT的示例方法
    public static Claims parseJWT(String jwt) {
        if (StrUtil.isBlank(jwt)) {
            return null;
        }
        Claims claims = Jwts.parser()
                .setSigningKey(DatatypeConverter.parseBase64Binary(SECRET_KEY))
                .parseClaimsJws(jwt).getBody();
        return claims;
    }

    /**
     * 获取用户id
     *
     * @param jwt
     * @return
     */
    public static String getUserId(String jwt) {
        try {
            Claims claims = null;
            claims = Jwts.parser()
                    .setSigningKey(DatatypeConverter.parseBase64Binary(SECRET_KEY))
                    .parseClaimsJws(jwt).getBody();

            return (String) claims.get("id");
        } catch (Exception e) {
            throw e;
        }
    }

    public static String getUserName(String jwt) {
        try {
            Claims claims = null;
            claims = Jwts.parser()
                    .setSigningKey(DatatypeConverter.parseBase64Binary(SECRET_KEY))
                    .parseClaimsJws(jwt).getBody();

            return (String) claims.get("name");
        } catch (Exception e) {
            throw e;
        }
    }

    public static String getCurrentUserId() {
        String userId = "";
        HttpServletRequest request = getRequest();
        if (null != request) {
            String jwt = request.getHeader("token");
            if (org.apache.commons.lang3.StringUtils.isNotBlank(jwt)) {
                userId = getUserId(jwt);
            }
        }
        return userId;
    }

    public static String getCurrentUserName() {
        String userName = "";
        HttpServletRequest request = getRequest();
        if (null != request) {
            String jwt = request.getHeader("token");
            if (org.apache.commons.lang3.StringUtils.isNotBlank(jwt)) {
                userName = getUserName(jwt);
            }
        }
        return userName;
    }

    /**
     * 获取request
     *
     * @return
     */
    public static HttpServletRequest getRequest() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return requestAttributes == null ? null : requestAttributes.getRequest();
    }

    /**
     * 获取token 当请求头中不含有token时返回空
     *
     * @return
     */
    public static String getToken() {
        HttpServletRequest request = getRequest();
        String token = null;
        if (null != request) {
            token = request.getHeader("token");
        }
        return token;

    }

    /**
     * @return
     */
    public static Claims getClaims() {
        return parseJWT(getToken());
    }

    /**
     * 获取系统ID
     *
     * @return
     */
    public static Integer getSystemId() {
        return getValue("systemId");
    }

    /**
     * 获取客户ID
     *
     * @return
     */
    public static Integer getCustomerId() {
        return getValue("customerId");
    }

    /**
     * 获取值
     *
     * @return
     */
    public static Integer getValue(String key) {
        Claims claims = getClaims();
        if (claims == null) {
            return null;
        }
        Object value = claims.get(key);
        if (value == null) {
            return null;
        }
        return (Integer) value;
    }


    /*public static void main(String[] args) {
        JwtUtils jwtUtils = new JwtUtils();

        //System.out.println(jwtUtils.getJwtTokenByEmail("1", "100000001", "张三", true));


        System.out.println(jwtUtils.getUserName("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJjdHJtIiwiaWF0IjoxNjg0ODExMTYxLCJleHAiOjE2ODQ4OTc1NjEsImlkIjoiMSIsImFjY291bnQiOiIxMDAwMDAwMDEiLCJuYW1lIjoi5byg5LiJIn0.wRYmxoUDKnW7emlIGm0e89bpxFzweBRisaTrhiqi00k"));
    }*/
}
